/**
 * Copyright 2017 orivil Authors. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package swagger

import (
	"gitee.com/tugoer/orivil/param"
)

type Operation struct {
	// A list of tags for API documentation control. Tags can be
	// used for logical grouping of operations by resources or
	// any other qualifier.
	Tags []string `json:"tags,omitempty"`

	// A short summary of what the operation does. For maximum readability
	// in the swagger-ui, this field SHOULD be less than 120 characters.
	Summary string `json:"summary,omitempty"`

	// A verbose explanation of the operation behavior.
	// GFM(https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown)
	// syntax can be used for rich text representation.
	Description string `json:"description,omitempty"`

	// Additional external documentation for this operation.
	ExternalDocs *ExternalDoc `json:"externalDocs,omitempty"`

	// Unique string used to identify the operation. The id MUST be unique
	// among all operations described in the API. Tools and libraries MAY use
	// the operationId to uniquely identify an operation, therefore, it is
	// recommended to follow common programming naming conventions.
	OperationId string `json:"operationId,omitempty"`

	// A list of MIME types the operation can consume. This overrides the consumes
	// definition at the Swagger Object. An empty value MAY be used to clear the
	// global definition. Value MUST be as described under
	// Mime Types(http://swagger.io/specification/#mimeTypes).
	Consumes []MimeType `json:"consumes,omitempty"`

	// A list of MIME types the operation can produce. This overrides the produces
	// definition at the Swagger Object. An empty value MAY be used to clear the
	// global definition. Value MUST be as described under
	// Mime Types(http://swagger.io/specification/#mimeTypes).
	Produces []MimeType `json:"produces,omitempty"`

	// A list of parameters that are applicable for this operation. If a parameter is
	// already defined at the Path Item(http://swagger.io/specification/#pathItemParameters),
	// the new definition will override it, but can never remove it. The list MUST NOT
	// include duplicated parameters.
	// A unique parameter is defined by a combination of a
	// name(http://swagger.io/specification/#parameterName) and
	// location(http://swagger.io/specification/#parameterIn).
	// The list can use the Reference Object(http://swagger.io/specification/#referenceObject)
	// to link to parameters that are defined at the Swagger Object's
	// parameters(http://swagger.io/specification/#swaggerParameters).
	// There can be one "body" parameter at most.
	Parameters Parameters `json:"parameters,omitempty"`

	// Required.
	// The list of possible responses as they are returned from executing this operation.
	Responses Responses `json:"responses"`

	// The transfer protocol for the operation.
	// Values MUST be from the list: "http", "https", "ws", "wss".
	// The value overrides the Swagger Object schemes definition.
	Schemes []string `json:"schemes,omitempty"`

	// Declares this operation to be deprecated. Usage of the declared operation should be
	// refrained. Default value is false.
	Deprecated bool `json:"deprecated,omitempty"`

	// A declaration of which security schemes are applied for this operation. The list
	// of values describes alternative security schemes that can be used (that is, there
	// is a logical OR between the security requirements). This definition overrides any
	// declared top-level security. To remove a top-level security declaration, an empty
	// array can be used.
	Security []SecurityRequirement `json:"security,omitempty"`
}

func (op *Operation) AddParameters(ps []*param.Parameter) *Operation {
	if len(op.Consumes) == 0 {
		op.Consumes = []MimeType{"application/x-www-form-urlencoded"}
	}
	op.Parameters = NewParameters(ps)
	for _, p := range op.Parameters {
		if p.Type == "file" {
			op.Consumes = []MimeType{"multipart/form-data"}
		}
	}
	return op
}

func (op *Operation) AppendResponses(ress Responses) *Operation {
	if op.Responses == nil {
		op.Responses = ress
	} else {
		for key, res := range ress {
			op.Responses[key] = res
		}
	}
	return op
}
